object Cyclic {
	class Foo[t]
	class Rec[t <: Foo[t]]

	trait TFoo {type t}
	// class TRec[t_ <: TFoo{type t=t_}]
	//                         ^
	// error: illegal cyclic reference involving type t_
}

/* GOT: 
error: illegal inheritance;
 self-type Bottom.this.selfT does not conform to java.lang.Object's selftype java.lang.Object
        trait Derived requires selfT extends Base 
                                             ^
error: illegal inheritance;
 self-type Bottom.this.selfT does not conform to scala.ScalaObject's selftype scala.ScalaObject
        trait Derived requires selfT extends Base 
                                     ^
CODE: THIS WAS A BUG IN MY BRAIN --> order of compound types for bound on Requirements was wrong
trait Top {	
	trait Base
	type selfT
} 

trait Bottom[Requirements <: Bottom[Requirements] with Top  ] requires Requirements {
	type selfT <: Derived with Base 

	trait Derived requires selfT extends Base 
}

EXPECTED: same behaviour as:  (i.e compiler happy)
trait Top {	
	trait Base
	type selfT
} 

trait Bottom extends Top {
	type selfT <: Derived with Base 
	
	trait Derived requires selfT extends Base 
}*/


trait Top {	
	trait Base
	type selfT
} 

trait Bottom[Requirements <:  Top with Bottom[Requirements]  ] requires Requirements {
	type selfT <: Derived with Base 

	trait Derived requires selfT extends Base 
}


/*trait Bla {
	type TBifunctor <: BifunctorBase

	trait BifunctorBase requires TBifunctor {
		type s <: TBifunctor 

		def bimap() :s{type s=BifunctorBase.this.s}	
	}

	type TListF <: ListFBase with TBifunctor
	trait ListFBase requires TListF extends BifunctorBase {
			type s = TListF
	}
	
	type TNilF <: TListF with NilFBase 
	
	def NilF() :TNilF
	trait NilFBase requires TNilF extends ListFBase {
		def bimap() :TNilF = NilF()
	}
	
}
*/

/*trait BlaParam {
	trait BifunctorBase[s <:BifunctorBase[s]] requires s {
		def bimap() :s
	}

	type TListF <: ListFBase 
	trait ListFBase requires TListF extends BifunctorBase[TListF] {
	}
	
	def make() :TListF
	trait NilFBase requires TListF extends ListFBase {
		def bimap() :TListF = make()
	}
}*/

/*trait Bla {
	type TBifunctor <: BifunctorBase{type s = TBifunctor}
	trait BifunctorBase requires TBifunctor {
		type s <: TBifunctor
		def bimap() :s
	}

	type TListF <: ListFBase 
	trait ListFBase requires TListF extends BifunctorBase{
		type s = TListF
	}
	
	def make() :TListF
	trait NilFBase requires TListF extends ListFBase {
		def bimap() :TListF = make()
	}
}*/

// type members, unlike type parameters, are not in scope in 
// the primary constructor or in the requires clause
trait Scoping {
	class Foo[t](val some :t)

	// abstract class TFoo(val some :tt)  { type tt }
	// not found: type tt --------^
	// strangely enough, this compiles (bug #593)
	// trait TFoo(val some :tt)  { type tt }
	
	// type member is not in scope in the requires clause
	// only works if a self type is assumed to always be a subtype 
	// of the defining class (otherwise the typemember isn't available)
	class FooReq[t <:FooReq[t]] requires t
	// class TFooReq requires t {type t <:TFooReq}
	// not found: type t -----^
}

// would be nice to have 
/*trait NiceToHaves {
// in context of virtual class encoding for parameterised classes:
	type TFoo[s] <: FooBase[s]
	
	class FooBase[s] requires TFoo[s]
	
// subtyping for higher-kinded types:
    type TFoo <: FooBase

// "partial application" of type parameters
	class Fix[a, s/*nop*/ <: s[a,?]](out :s[a,Fix[s/*nop*/,a]])
	
	trait ListF[a, b]
	type List = Fix[Int, ListF]
}*/


// ok:
trait MalformedType {
	type TFoo <: Foo
	trait Foo requires TFoo {
		type s <: TFoo

		def bar :s
	}
	
	def manip[tf <:TFoo, t](x :t, f :t=>tf{type s=tf}) = f(x).bar
}

// This is a simplified version of an attempt at making my encoding of lightweight PolyP
// extensible using a virtual class encoding -- the code isn't really meaningful anymore, but
// it's the simplest piece of code I've been able to construct that still exhibits the crash.
// There's a type error (due to the piece of code I commented out), but I'd prefer a nice 
// "types do not match" error over a long stack trace ;-)
/*trait CrashDueToTypeError {
	def id[a](x :a) :a = x

	trait Bifunctor {
		type a; //	 content 
		type s <: Bifunctor

		// uncomment        this-vvvvvvvvvvvvvvvvvvvvvvvvvvvv, and it compiles
		def bimap[c](f :a=>c) :s{/*type s=Bifunctor.this.s;*/type a=c; }
	}

	def hylo[hs <: Bifunctor,ha,hb,hc]
	    (f :hb=>hs{type s=hs; type a=ha}, 
	     g :hs{type s=hs; type a=ha}=>hc)(x :hb) 
	     :hc 
	     = g(f(x).bimap(id))
}*/
/*
Exception in thread "main" java.lang.Error
        at scala.tools.nsc.symtab.Symbols$NoSymbol$.owner(Symbols.scala:1070)
        at scala.tools.nsc.symtab.Types$$anonfun$26.apply(Types.scala:1502)
        at scala.tools.nsc.symtab.Types$$anonfun$26.apply(Types.scala:1500)
        at scala.List.forall(List.scala:823)
        at scala.tools.nsc.symtab.Types$class.isSubScope$0(Types.scala:1499)
        at scala.tools.nsc.symtab.Types$class.isSameType(Types.scala:1504)
        at scala.tools.nsc.symtab.SymbolTable.isSameType(SymbolTable.scala:10)
        at scala.tools.nsc.symtab.Types$Type.$eq$colon$eq(Types.scala:251)
        at scala.tools.nsc.symtab.Types$$anonfun$36.apply(Types.scala:1693)
        at scala.tools.nsc.symtab.Types$$anonfun$36.apply(Types.scala:1692)
        at scala.List$.forall2(List.scala:306)
        at scala.tools.nsc.symtab.Types$class.matchingParams(Types.scala:1692)
        at scala.tools.nsc.symtab.Types$class.isSubType0(Types.scala:1596)
        at scala.tools.nsc.symtab.SymbolTable.isSubType0(SymbolTable.scala:10)
        at scala.tools.nsc.symtab.Types$class.isSubType(Types.scala:1544)
        at scala.tools.nsc.symtab.SymbolTable.isSubType(SymbolTable.scala:10)
        at scala.tools.nsc.symtab.Types$Type.$less$colon$less(Types.scala:243)
        at scala.tools.nsc.symtab.Types$class.scala$tools$nsc$symtab$Types$$specializesSym(Types.scala:1662)
        at scala.tools.nsc.symtab.Types$$anonfun$35.apply(Types.scala:1654)
        at scala.tools.nsc.symtab.Types$$anonfun$35.apply(Types.scala:1654)
        at scala.List.exists(List.scala:839)
        at scala.tools.nsc.symtab.Types$class.specializesSym(Types.scala:1653)
        at scala.tools.nsc.symtab.SymbolTable.specializesSym(SymbolTable.scala:10)
        at scala.tools.nsc.symtab.Types$Type.specializes(Types.scala:257)
        at scala.tools.nsc.symtab.Types$$anonfun$31.apply(Types.scala:1613)
        at scala.tools.nsc.symtab.Types$$anonfun$31.apply(Types.scala:1613)
        at scala.List.forall(List.scala:823)
        at scala.tools.nsc.symtab.Types$class.isSubType0(Types.scala:1613)
        at scala.tools.nsc.symtab.SymbolTable.isSubType0(SymbolTable.scala:10)
        at scala.tools.nsc.symtab.Types$class.isSubType(Types.scala:1544)
        at scala.tools.nsc.symtab.SymbolTable.isSubType(SymbolTable.scala:10)
        at scala.tools.nsc.symtab.Types$Type.$less$colon$less(Types.scala:243)
        at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$inferView(Typers.scala:61)
        at scala.tools.nsc.typechecker.Typers$Typer.inferView(Typers.scala:76)
        at scala.tools.nsc.typechecker.Typers$Typer.adaptToMember(Typers.scala:492)
        at scala.tools.nsc.typechecker.Typers$Typer.tryTypedApply$0(Typers.scala:1124)
        at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:1509)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1625)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1655)
        at scala.tools.nsc.typechecker.Typers$Typer.transformedOrTyped(Typers.scala:1689)
        at scala.tools.nsc.typechecker.Typers$Typer.typedDefDef(Typers.scala:813)
        at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:1304)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1625)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1651)
        at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$45.apply(Typers.scala:973)
        at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$45.apply(Typers.scala:963)
        at scala.List$.loop$0(List.scala:232)
        at scala.List$.mapConserve(List.scala:249)
        at scala.List$.loop$0(List.scala:236)
        at scala.List$.mapConserve(List.scala:249)
        at scala.List$.loop$0(List.scala:236)
        at scala.List$.mapConserve(List.scala:249)
        at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:963)        
        at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:687)
        at scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:625)
        at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:1295)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1625)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1651)
        at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$45.apply(Typers.scala:973)
        at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$45.apply(Typers.scala:963)
        at scala.List$.loop$0(List.scala:232)
        at scala.List$.mapConserve(List.scala:249)
        at scala.List$.loop$0(List.scala:236)
        at scala.List$.mapConserve(List.scala:249)
        at scala.List$.loop$0(List.scala:236)
        at scala.List$.mapConserve(List.scala:249)
        at scala.List$.loop$0(List.scala:236)
        at scala.List$.mapConserve(List.scala:249)
        at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:963)        
        at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:1291)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1625)
        at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:1651)
        at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$1.apply(Analyzer.scala:38)
        at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:210)
        at scala.tools.nsc.Global$GlobalPhase$$anonfun$1.apply(Global.scala:199)        
        at scala.tools.nsc.Global$GlobalPhase$$anonfun$1.apply(Global.scala:199)        
        at scala.Iterator$class.foreach(Iterator.scala:285)
        at scala.collection.mutable.ListBuffer$$anon$0.foreach(ListBuffer.scala:216)
        at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:199)
        at scala.tools.nsc.Global$Run.compileSources(Global.scala:429)
        at scala.tools.nsc.Global$Run.compile(Global.scala:487)
        at scala.tools.nsc.Main$.process(Main.scala:60)
        at scala.tools.nsc.Main$.main(Main.scala:82)
        at scala.tools.nsc.Main.main(Main.scala)*/

/*trait TypeConstructor {
	type a
}

class Param[T <: TypeConstructor](foo :T{type a=Int}) {
	def get :T = foo
	def manip(a :T{type a=Int}) :Param[T] = new Param(a) // identity for brevity
	
}

trait TypeMember {
	type T <: TypeConstructor
	val foo :T{type a=Int}
	
	def get :T = foo
	def manip(a :T{type a=Int}) :TypeMember{type T=TypeMember.this.T} = 
		new TypeMember{val foo = a; type T = TypeMember.this.T }
	
}



trait Cell extends TypeConstructor {
	val contents :a
}

*/
